package org.example.mybatis.proxy;

import org.example.mybatis.annotation.Param;
import org.example.mybatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Mapper接口代理类
 */
public class MapperProxy<T> implements InvocationHandler {
    private static final Logger logger = LoggerFactory.getLogger(MapperProxy.class);

    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;

    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 如果是Object类的方法，直接调用
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }

        // 获取完全限定名
        String statementId = mapperInterface.getName() + "." + method.getName();
        logger.info("调用方法: {}", statementId);

        // 处理多参数情况，将参数封装为Map
        Object param = null;
        if (args != null && args.length > 0) {
            if (args.length == 1) {
                param = args[0];
            } else {
                // 处理多参数情况
                param = convertArgsToParamMap(method, args);
            }
        }

        // 根据方法返回值类型和方法名判断操作类型
        String methodName = method.getName();
        Class<?> returnType = method.getReturnType();

        // 判断是否为查询操作
        if (methodName.startsWith("select")) {
            if (Collection.class.isAssignableFrom(returnType)) {
                // 返回值是集合类型，执行查询多条
                return sqlSession.selectList(statementId, param);
            } else {
                // 返回值是单个对象，执行查询单条
                return sqlSession.selectOne(statementId, param);
            }
        } else if (methodName.startsWith("insert")) {
            // 插入操作
            return sqlSession.insert(statementId, param);
        } else if (methodName.startsWith("update")) {
            // 更新操作
            return sqlSession.update(statementId, param);
        } else if (methodName.startsWith("delete")) {
            // 删除操作
            return sqlSession.delete(statementId, param);
        }

        // 未知操作类型，默认执行查询
        return sqlSession.selectOne(statementId, param);
    }

    /**
     * 将多个参数转换为Map
     */
    private Object convertArgsToParamMap(Method method, Object[] args) {
        Map<String, Object> paramMap = new HashMap<>();
        Parameter[] parameters = method.getParameters();

        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            // 处理@Param注解
            if (parameter.isAnnotationPresent(Param.class)) {
                Param param = parameter.getAnnotation(Param.class);
                paramMap.put(param.value(), args[i]);
            } else {
                // 没有注解的参数，使用参数索引作为名称
                paramMap.put("param" + (i + 1), args[i]);

                // 如果是单个基本类型参数，添加一个arg前缀的映射
                if (args[i] != null) {
                    paramMap.put("arg" + i, args[i]);
                }
            }
        }

        return paramMap;
    }
}